<?php

namespace process;

use app\service\modbus\ModbusRtuOrTcpService;
use app\service\modbus\ModbusTcpService;
use plugin\admin\app\model\IotDevice;
use plugin\admin\app\model\IotDeviceType;
use plugin\admin\app\model\IotSignal;
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Crontab\Crontab;
use Workerman\Mqtt\Client;

class IoTTask
{

    public function onWorkerStart()
    {
        // 每2分钟执行一次
        new Crontab('*/30 * * * * *', function(){
            $this->isModbusTcpDeviceOnline();
        });
    }

    /**
     * ModbusTcp设备是否在线
     * @return void
     */
    private function isModbusTcpDeviceOnline()
    {
        $iot_device_data = IotDevice::whereNotNull('ip')->whereNotNull('port')->select(['id','ip','port','status','model','is_lecp_server','lecp_server_name','device_type_id'])->get();
        $action = "plc_read_node";
        $date = date("Y-m-d H:i:s");
        if ($iot_device_data){
            foreach ($iot_device_data as $value){
                $id = $value->id;
                $ip = $value->ip;
                $port = $value->port;
                $type_name = $value->type_name;
                $lecp_server_name = $value->lecp_server_name;
                $is_lecp_server = $value->is_lecp_server;
                $model_id = $value->model;
                //获取那些类型
                if ($type_name){
                    if ($type_name=="modbus"){
                        $modbus_tcp = new ModbusTcpService($ip,$port);
                        $is_online = $modbus_tcp->isOnline();
                        IotDevice::where('id', $id)->update(['status' => $is_online,'updated_time'=>$date]);
                    }elseif ($type_name=="plc"){
                        $status = "offline";
                        if ($lecp_server_name && $is_lecp_server==1){
                            //LECPServer 服务插件,如果配置地址表示不在线,配置的要与软件上一一对应,不然值会出错
                            $address = IotSignal::where('model_id',$model_id)->value('address');
                            if ($address){
                                $uri = "http://{$ip}:{$port}";
                                $node="NODES.{$lecp_server_name}.{$address}";
                                $data = json_encode(['action'=>$action,'node'=>$node]);
                                $rtval = http_post($uri,$data);
                                if ($rtval){
                                    if ($rtval['errcode']==0){
                                        $status = "online";
                                    }
                                }
                            }
                        }
                        IotDevice::where('id', $id)->update(['status' => $status,'updated_time'=>$date]);
                    }elseif ($type_name=="mqtt"){
                        try {
                            $mqtt = new Client("mqtt://{$ip}:{$port}");
                            $mqtt->onConnect = function ($mqtt) use ($id,$date) {
                                IotDevice::where('id', $id)->update(['status' => "online",'updated_time'=>$date]);
                            };
                            $mqtt->onClose=function ($mqtt)use($id,$date){
                                IotDevice::where('id', $id)->update(['status' => "offline",'updated_time'=>$date]);
                                $mqtt->close();
                            };
                            $mqtt->connect();
                        }catch (\Exception $e){
                            $status = "offline";
                            IotDevice::where('id', $id)->update(['status' => $status,'updated_time'=>$date]);
                        }
                    }elseif ($type_name=="tcp"){
                        $async_tcp_connection = new AsyncTcpConnection("tcp://{$ip}:{$port}");
                        $async_tcp_connection->onConnect=function (AsyncTcpConnection $async_tcp_connection)use($id,$date){
                            IotDevice::where('id', $id)->update(['status' => "online",'updated_time'=>$date]);
                        };
                        $async_tcp_connection->onError=function (AsyncTcpConnection $async_tcp_connection, $code, $msg)use($id,$date){
                            $async_tcp_connection->close();
                            IotDevice::where('id', $id)->update(['status' => "offline",'updated_time'=>$date]);
                        };
                        $async_tcp_connection->onClose=function (AsyncTcpConnection $async_tcp_connection)use($id,$date){
                            IotDevice::where('id', $id)->update(['status' => "offline",'updated_time'=>$date]);
                            $async_tcp_connection->close();
                        };
                        $async_tcp_connection->connect();
                    }elseif ($type_name=="dtu") {
                        //采用modbus-rtu-tcp的方式获取数据
                        $modbus__rtu_tcp = new ModbusRtuOrTcpService($ip, $port);
                        $is_online = $modbus__rtu_tcp->isOnline();
                        $online_time="--";
                        $unline_time="--";
                        if ($is_online == "online") {
                            $online_time = $date;
                        } elseif ($is_online == "offline") {
                            $unline_time = $date;
                        }
                        $new_switch_time = implode("/", [$online_time, $unline_time]);
                        IotDevice::where('id', $id)->update(['status' => $is_online, 'updated_time' => $date, 'switch_time' => $new_switch_time]);
                    }
                }
            }
        }
    }
}
